__license__ = "MIT License <http://www.opensource.org/licenses/mit-license.php>"
__copyright__ = "2005, Tiago Cogumbreiro"
__author__ = "Tiago Cogumbreiro <cogumbreiro@users.sf.net>"

import re
from UserDict import UserDict

class CueParser:
    QUOTED = "\"(.+)\""
    NON_WHITE = "([^\s]+)"
    TIME = "([0-9][0-9]:[0-5][0-9]:[0-9][0-9])"
    CENT = "([0-9][0-9])"

    strip = lambda foo: "^\s*" + foo + "\s*$"
    tokens = lambda *args: re.compile(strip("\s+".join(args)))
    
    grammar = dict(
        audio_track=tokens("TRACK", CENT, "AUDIO"),
        binary_track=tokens("TRACK", CENT, "MODE([1-2])/([0-9]{4,4})"),
        performer=tokens("PERFORMER", QUOTED),
        title=tokens("TITLE", QUOTED),
        rem=tokens("REM", ".*"),
        flags=tokens("FLAGS", "([A-Z0-9]{3,3})"),
        index=tokens("INDEX", CENT, TIME),
        post_gap=tokens("POSTGAP", TIME),
        binary_file=("FILE", QUOTED, "BINARY"),
        file=tokens("FILE", QUOTED, NON_WHITE),
        cdtext=tokens("CDTEXTFILE", QUOTED),
    )

    @classmethod
    def parse_file(self, buff, handler):
        void_method = lambda *args, **kwargs: None
        
        for line in buff.readline():
            for key, regex in self.grammar:
                m = regex.match(line)
                if m is None:
                    continue
                
                meth = getattr(handler, "on_" + key, void_method)
                
                meth(line, m)

class ScopeVariable(object):
    class Variable:
        def __init__(self, **kwargs):
            for key, value in kwargs.iteritems():
                setattr(self, key, value)

                
    def __init__(self):
        self._vars = []
        self._level = 0
    
    def set_level(self, level):
        self._level = level
        for var in self._vars:
            if var.level > self._level:
                self._vars.remove(var)
    
    def get_level(self):
        return self._level

    level = property(get_level, set_level)
    
    def push(self):
        self.level += 1

    def pop(self):
        self.level -= 1
    
    def set_value(self, value):
        if len(value) > 0 and self._vars[-1].level == self._level:
            self._vars[-1].value = value
        else:
            self._vars.append(Variable(value=value, level=self._level)
    
    def get_value(self):
        if len(self._vars) == 0:
            raise ValueError
            
        return self._vars[-1]

class ScopeDict(UserDict):
    def __init__(self, keys):
        self.data = {}
        for key in keys:
            self.data[key] = ScopeVariable()
        self._level = 0

    def __setitem__(self, key, value):
        self.data[key].value = value

    def __getitem__(self, key):
        return self.data[key].value

    def set_level(self, level):
        for var in self.data.values():
            var.level = level
        self._level = level
        
    def get_level(self):
        return self._level

    level = property(get_level, set_level)

    def push(self):
        self.level += 1

    def pop(self):
        self.level -= 1

#####
# FILE
# |
# +-- TRACK
#     |
#     +--TITLE
#     |
#     +--PERFORMER

class Track:
    indexes = []

class CueSpliter:
    depth = 0
    
    class Handler:
        def __init__(self):
            self.vars = ScopeDir("performer", "title")
            self.files = []
            self.track_num = -1
            self.tracks = {}
            
        def on_file(self, line, match):
            self.vars.level = 1
            
        def on_audio_track(self, line, match):
            self.vars.level = 2
            self.track_num = int(match.group(1))

        def on_index(self, line, match):
            self.

def cue_spliter(buff):

